<template>
  <div
      class="simple-qr-code"
      v-on="$listeners"
      :style="`background-color: ${background}`"
  >
    <canvas ref="myCanvas" class="qrcode-canvas" />
    <slot name="default"></slot>
  </div>
</template>

<script type="text/ecmascript-6">
import QRCode from "qrcode";

export default {
  props: {
    /**
     * 被编入二维码的值
     */
    value: {
      type: String,
    },
    margin: {
      type: [Number, String],
      default: "2.5vh",
    },
    background: {
      type: String,
      default: "#ffffff",
    },
    color: {
      type: String,
      default: "#000000",
    },
    icon: {
      type: String,
    },
  },
  data() {
    return {
      qrcode: undefined,
      url: "",
      logo: null,
      ctx: null,
    };
  },
  methods: {
    drawQrCode(value) {
      if (!this.$refs.myCanvas) {
        return;
      }
      if (!this.ctx) {
        this.ctx = this.$refs.myCanvas.getContext("2d");
      }

      if (!value) {
        this.$refs.myCanvas.width = this.$el.clientWidth;
        return;
      }

      let margin = 0;
      if (typeof this.margin === "number") {
        margin = this.margin;
      } else if (this.margin.endsWith("vh")) {
        margin = parseFloat(this.margin);
        margin = Math.ceil((margin * window.innerWidth) / 100);
      } else if (this.margin) {
        margin = parseFloat(this.margin);
        const fontSize = parseFloat(document.documentElement.style.fontSize);
        margin = Math.ceil(margin * fontSize);
      }

      QRCode.toDataURL(value, {
        margin: 0,
        width: this.$refs.myCanvas.width,
        height: this.$refs.myCanvas.height,
        color: {
          dark: this.color,
          light: this.background,
        },
      }).then((url) => {
        const img = new Image();
        this.url = url;
        this.$emit("update:url", url);
        img.src = url;
        img.onload = () => {
          this.ctx.drawImage(
              img,
              margin,
              margin,
              this.$refs.myCanvas.width - margin * 2,
              this.$refs.myCanvas.height - margin * 2
          );
          this.drawLogo();
        };
      });
    },
    onResize() {
      if (!this.$refs.myCanvas) return;
      this.$refs.myCanvas.width = this.$el.clientWidth;
      this.$refs.myCanvas.height =
          this.$el.clientHeight || this.$el.clientWidth;
      this.$nextTick(() => this.drawQrCode(this.value));
    },
    drawLogo() {
      if (this.icon) {
        const ctx = this.ctx;
        const size = this.$refs.myCanvas.width * 0.25;
        const left = (this.$refs.myCanvas.width - size) / 2;
        const top = (this.$refs.myCanvas.height - size) / 2;
        ctx.drawImage(this.logo, left, top, size, size);
      }
    },
  },
  components: {},
  mounted() {
    this.onResize();
  },
  watch: {
    value() {
      if (this.$el) {
        this.drawQrCode(this.value);
      }
    },
    icon() {
      if (this.logo) {
        this.logo.src = this.icon;
        this.drawLogo();
      }
    },
  },
  created() {
    this.logo = new Image();
    this.logo.src = this.icon;
    window.addEventListener("resize", this.onResize);
  },
  destroyed() {
    window.removeEventListener("resize", this.onResize);
  },
};
</script>

<style scoped lang="less">
.simple-qr-code {
  display: inline-block;
  vertical-align: middle;
  width: 100%;
  height: 100%;
  border-radius: 8px;
  overflow: hidden;
  position: relative;
  text-align: center;

  .qrcode-canvas {
    vertical-align: middle;
  }
}
</style>